package com.example.flashsales.service.impl;

import com.example.flashsales.entity.dto.*;
import com.example.flashsales.entity.pojo.User;
import com.example.flashsales.entity.pojo.UserCostRecord;
import com.example.flashsales.entity.vo.*;
import com.example.flashsales.mappers.UserMapper;
import com.example.flashsales.service.RefundService;
import com.example.flashsales.service.UserCostRecordService;
import com.example.flashsales.service.UserService;
import com.github.pagehelper.PageHelper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserCostRecordServiceImpl userCostRecordService;

    @Autowired
    AdminCostRecordServiceImpl adminCostRecordService;

    @Autowired
    UserRecordServiceImpl userRecordService;

    @Autowired
    OrderCarServiceImpl orderCarServiceImpl;

    @Autowired
    OrderServiceImpl orderServiceImpl;

    @Autowired
    GoodsServiceImpl goodsServiceImpl;

    @Autowired
    RefundServiceImpl refundServiceImpl;

    @Autowired
    StoreServiceImpl storeService;

    @Autowired
    UserMapper userMapper;



    /**
     * 用户查看所有商品，去商品表查看（这个查看只是初步查看有哪些商品）
     * @return 返回所有商品的视图对象集合
     */
    public List<GoodsVo> viewAllGoods(int num,int page){
        return goodsServiceImpl.viewAllGoods(num,page);
    }


    /**
     * 按类别查看商品（直接去商品表里面查询）
     * @param goodsDto 类别id
     * @return 返回改类别的所有视图对象集合
     */
    public List<GoodsVo> viewGoodsByType(GoodsDto goodsDto,int num,int page){
        return goodsServiceImpl.viewGoodsByType(goodsDto,num,page);
    }

    /**
     * 按商品名称查看商品（模糊查询，可输入一个字找到与之有关的集合，直接去商品表里面查询）
     * @param name 商品名称
     * @return 返回与改名字有关的所有视图对集合
     */
    public List<GoodsVo> viewGoodsByName(String name,int num,int page){
        return goodsServiceImpl.viewGoodsByName(name,num,page);
    }


    /**
     * 查看商品的具体信息
     * @param id 商品id
     * @return 返回商品的具体信息 包括类别 与描述
     */
    public GoodsVo viewGoodsMessage(long id){
        return goodsServiceImpl.viewGoodsMessage(id);
    }


    /**
     * 用户查看自己的订单
     * @param userId 用户id
     * @return 返回用户的订单视图对象列表
     */
    public Map<String,Object> viewOrders(long userId,int page,int num){
        final Integer integer = orderServiceImpl.viewUserOrderCount(userId);
        Map<String,Object> map = new HashMap<>();
        map.put("total",integer);
        map.put("message",orderServiceImpl.viewOrders(userId, page, num));
        return map;
    }


    /**
     * 用户按时间查看自己的订单
     * @param userId 用户id
     * @param qDate 前一天
     * @param hDate 后一天
     * @return 返回用户的订单视图对象列表
     */
    public Map<String,Object> viewOrdersByTime(long userId,Date qDate,Date hDate,int page,int num){
        final Integer integer = orderServiceImpl.viewUserOrderCountByTime(userId,qDate,hDate);
        Map<String,Object> map = new HashMap<>();
        map.put("total",integer);
        map.put("message",orderServiceImpl.viewOrdersByTime(userId, qDate, hDate, page, num));
        return map;

    }




    /**
     * 查看店家信息
     * @param storeId 店家id
     * @return 返回店家视图对象
     */
    @Override
    public StoreVo viewStoreMessage(long storeId) {
        return storeService.viewStoreMessage(storeId);
    }


    /**
     * 用户添加商品进入购物车 （调用OrderCarService里面的addGoodsInOrderCar方法）
     * @param userId 用户id
     * @return 返回是否添加成功
     */
    public String addGoodsInOrderCar(long userId, OrderCarDetailsDto orderCarDetailsDto){
        return orderCarServiceImpl.addGoodsInOrderCar(orderCarDetailsDto, userId);
    }


    /**
     * 用户修改自己购物车里面商品的数据 (调用OrderCarService里面的changeOrderCarGoodsCount方法)
     * @param userId  用户id
     * @return 返回是否修改成功
     */
    public String changeOrderCarGoodsCount(long userId,OrderCarDetailsDto orderCarDetailsDto){
        return orderCarServiceImpl.changeOrderCarGoodsCount(orderCarDetailsDto, userId);
    }


    /**
     * 用户删除购物车里面的数据（调用OrderCarService里面的deleteGoodsInOrderCar方法）
     * @param userId 用户id
     * @return 返回是否删除成功
     */
    public String deleteGoodsInOrderCar(long userId,OrderCarDetailsDto orderCarDetailsDto){
        return orderCarServiceImpl.deleteGoodsInOrderCar(orderCarDetailsDto, userId);
    }


    /**
     * 用户清空购物车
     * @param userId 用户id
     * @return 返回是否清除成功
     */
    @Override
    public String cleanOrderCar(long userId) {
        return orderCarServiceImpl.cleanOrderCar(userId);
    }


    /**
     * 用户查看自己的购物车数据
     * @param userId 用户id
     * @return 购物车细节的视图对象
     */
    @Override
    public List<OrderCarDetailsVo> viewUserOrderCarMessage(long userId) {
        return orderCarServiceImpl.viewUserOrderCarMessage(userId);
    }

    /**
     * 用户查看自己信息
     * @param userId 用户id
     * @return 返回用户视图对象
     */
    @Override
    public UserVo viewUserMessage(long userId) {
        final User user = userMapper.viewUserMessage(userId);
        if (user == null){
            return null;
        }
        UserVo userVo = new UserVo();

        BeanUtils.copyProperties(user,userVo);
        return userVo;
    }


    /**
     * 用户修改密码（知道原密码，直接通过原密码修改）
     * @param userId 用户id
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     * @return 返回是否修改成功
     */
    public String modifyPasswordByPassword(long userId,String oldPassword,String newPassword){
        final User user = userMapper.viewUserMessage(userId);
        if (newPassword == null || oldPassword == null || oldPassword.equals("") || newPassword.equals("")){
            return "修改失败，原密码或新密码不能为空";
        }
        if (!user.getPassword().equals(oldPassword)){
            return "修改失败，原密码错误";
        }
        if (userMapper.modifyPasswordByPassword(userId,newPassword) > 0) {
            return "修改成功";
        }
        return "修改失败";
    }


    /**
     * 用户修改密码(通过短信验证码修改)
     * @param phone 用户电话号码
     * @param newPassword 新的密码
     * @return 返回是否修改成功
     */
    public String modifyPasswordByPhoneNumber(String phone,String newPassword){
        if (newPassword == ""){
            return "新密码不能为空";
        }
        if (userMapper.modifyPasswordByPhoneNumber(phone,newPassword) > 0) {
            return "修改成功";
        }
        return "修改失败";
    }


    /**
     * 用户登录 （通过扫二维码登录）
     * @param phone 二维码包含的电话号码
     * @return 返回用户的视图对象
     */
    public UserVo loginByQrCode(String phone){
        final User user = userMapper.viewUserByPhone(phone);
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);
        return userVo;
    }


    /**
     * 用户登录（通过短信验证码登录）
     * @param phone 电话号码
     * @return 返回用户的视图对象
     */
    public UserVo loginByPhone(String phone){
        final User user = userMapper.viewUserByPhone(phone);
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);
        return userVo;
    }


    /**
     * 用户登录（通过电话号码和密码登录）
     * @param phone 电话号码
     * @param password 密码
     * @return 返回用户信息的视图对象
     */
    public UserVo loginByPassword(String phone,String password){
        final User user = userMapper.loginByPassword(phone, password);
        if (user == null){
            return null;
        }
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);
        return userVo;
    }


    /**
     * 用户注册（通过扫描商家二维码注册 要调用StoreService里面的addUserCount方法）
     * @param userDto 用户信息 (电话号码，密码，店家id)
     * @return 返回是否注册成功
     */
    @Transactional
    public String register(UserDto userDto){
        final User user = userMapper.viewUserByPhone(userDto.getPhone());
        if (user != null){
            return "用户存在";
        }
        //先对用户表添加一条纪录 返回用户的id
        final int i = userMapper.addUser(userDto);
        if (i <= 0){
            //用户表增加失败
            return "用户注册失败";
        }
        //先在拉人纪录表里面添加一条纪录
        long userId = userDto.getId();
        if (userRecordService.addRecord(userId,userDto.getStoreId())) {
            if (userDto.getStoreId() == 0){
                //给用户增加一个购物车
                OrderCarDto orderCarDto = new OrderCarDto();
                orderCarDto.setUserId(userId);
                if (orderCarServiceImpl.addOrderCar(orderCarDto) > 0) {
                    return "注册成功";
                }
            }else {
                //增加成功
                //再调用StoreService里面的addUserCount方法 给商家增加一条纪录
                if (storeService.addUserCount(userDto.getStoreId(),1)) {
                    //给用户增加一个购物车
                    OrderCarDto orderCarDto = new OrderCarDto();
                    orderCarDto.setUserId(userId);
                    if (orderCarServiceImpl.addOrderCar(orderCarDto) > 0) {
                        //修改商家余额
                        final StoreVo storeVo = storeService.viewStoreMessage(userDto.getStoreId());
                        if (storeService.updateMoney(storeVo.getId(),storeVo.getUserMoney(),1)) {
                            return "注册成功";
                        }
                    }
                }
            }
        }
        return "注册失败";
    }


    /**
     * TODO 再拉人纪录表里面添加一条纪录
     * @param userId 用户id
     * @param storeId 店家id
     * @return 返回是否添加成功
     */
    public boolean addUserRecord(long userId,long storeId){
        return false;
    }


    /**
     *  用户下单（状态改为4）
     * @param userId 用户id
     * @return 返回所需支付的金额
     */
    @Override
    @Transactional
    public MoneyVo setOrder(long userId,long storeId) {
        OrderDto orderDto  = new OrderDto();
        orderDto.setStoreId(storeId);
        orderDto.setUserId(userId);
        final List<OrderCarDetailsVo> list = orderCarServiceImpl.viewUserOrderCarMessage(userId);
        if (list.isEmpty()){
            return null;
        }
        orderDto.setMoney(list.get(0).getAllMoney());
        Map<Long,Double> map = new HashMap<>();
        for (OrderCarDetailsVo orderCarDetailsVo : list) {
            map.put(orderCarDetailsVo.getGoodsId(),orderCarDetailsVo.getCount());
        }
        for (Long aLong : map.keySet()) {
            final GoodsVo goodsVo = goodsServiceImpl.viewGoodsMessage(aLong);
            if (goodsVo.getCount() < map.get(aLong)){
                return null;
            }
        }
        orderDto.setMap(map);
        if (orderServiceImpl.addOrder(orderDto)) {
            for (OrderCarDetailsVo orderCarDetailsVo : list) {
                //添加成功修改商品库存
                GoodsDto goodsDto = new GoodsDto();
                GoodsVo goodsVo = goodsServiceImpl.viewGoodsMessage(orderCarDetailsVo.getGoodsId());
                goodsDto.setId(orderCarDetailsVo.getGoodsId());
                goodsDto.setTypeId(goodsVo.getTypeId());
//                System.out.println(goodsVo.getCount());
                goodsDto.setCount(goodsVo.getCount()-orderCarDetailsVo.getCount());
                if (!goodsServiceImpl.updateGoodsMessage(goodsDto)) {
                    return null;
                }
            }
            //清空购物车
            orderCarServiceImpl.cleanOrderCar(userId);
        }
        MoneyVo moneyVo = new MoneyVo();
        moneyVo.setMoney(list.get(0).getAllMoney());
        moneyVo.setOrderId(orderDto.getId());
        return moneyVo;
    }


    /**
     * TODO 用户购买商品（通过支付宝或者微信）（一下购买都把订单状态改为6）
     * @param userId 用户id
     * @param storeId 店家id
     * @param map 商品集合 key为商品id,value为数量
     * @return 返回是否购买成功
     */
    @Override
    public String payMoneyByWeChatOrAlipay(long userId, long storeId, Map<Long, Integer> map,double money) {

        //TODO 调用AdminCostRecordService的add方法增加一条纪录
        return "购买失败";
    }


    /**
     * 用户购买物品（用余额购买）
     * @param userId 用户id
     * @param money 金额


     * @return 返回是否购买成功
     */
    @Override
    @Transactional
    public String payMoneyByBalance(long userId, double money, long orderId) {
        // 先查询余额是否充足
        double userMoney = viewUserMoney(userId);
        if (money > userMoney){
            return "余额不足";
        }
        // 修改订单状态
        final boolean b = orderServiceImpl.updateOrderState(orderId, 6);
        if (b){
            //修改订单的支付金额与支付方式
            if (orderServiceImpl.updateMoneyAndMethod(orderId,0,money)) {
                if (updateMoneyInUser(userId,money*-1)) {
                    //在商家流水纪录那里添加一条纪录
                    final String s = adminCostRecordService.addCostRecord(2, money);
                    if (s.equals("添加成功")){
                        if (userCostRecordService.addRecord(userId,orderId,money*-1,0,1)) {
                            return "购买成功";
                        }
                    }
                }
            }
        }
        return "购买失败";
    }


    /**
     * TODO 用户通过组合方式付款
     * @param userId 用户id
     * @param moneyW 已经支付金额
     * @param storeId 店家id
     * @param map 商品集合 key为商品id,value为数量
     * @param moneyY 需要余额支付的金额
     * @return 返回是否购买成功
     */
    @Override
    public String payMoneyByByWeChatOrAlipayAndBalance(long userId, double moneyW, long storeId, Map<Long, Integer> map, double moneyY) {
        return null;
    }





    /**
     * 用户查询自己的余额
     * @param userId 用户id
     * @return 返回double类型的余额
     */
    @Override
    public double viewUserMoney(long userId) {
        final UserVo userVo = viewUserMessage(userId);
        if (userVo == null){
            return 0.0;
        }
        return userVo.getMoney();
    }


    /**
     *用户退款
//     * @param orderId 订单id
//     * @param goods 商品id集合
//     * @param returnWhy 退款原因
     * @return 返回是否退款成功
     */
    @Override
    public String refund(RefundDto refundDto, List<RefundDetailsDto> refundDetailsDtoList) {
        return refundServiceImpl.refund(refundDto,refundDetailsDtoList);
    }


    /**
     * TODO 用户查看自己的订单退款清况
     * @param refundId 退款订单id
     * @return 返回是退款成功
     */
    @Override
    public ReturnOrderVo viewRefundDetails(long refundId) {
        return refundServiceImpl.viewRefundDetails(refundId);
    }

    /**
     * 查看所有
     * @param userId
     * @return
     */
    @Override
    public List<ReturnOrderVo> viewAllRefund(long userId) {
        return refundServiceImpl.viewAllRefundByUser(userId);
    }

    /**
     * 按类型查看
     * @param state
     * @param userId
     * @return
     */
    @Override
    public List<ReturnOrderVo> viewRefundByState(long state, long userId) {
        return refundServiceImpl.viewAllRefundByUserAndState(userId,state);
    }


    /**
     * TODO 修改余额
     * @param userId 用户id
     * @param money 变换的金额
     * @return 返回是否添加成功
     */
    @Override
    public boolean updateMoneyInUser(long userId, double money) {
        final UserVo userVo = viewUserMessage(userId);
        money = userVo.getMoney() + money;
        if (money < 0){
            return false;
        }
        return userMapper.updateMoney(userId,money) > 0;
    }

    /**
     * 按时间类型查看流水纪录
     * @param userId
     * @param state 0-支付，1-退款 2全部
     * @param page
     * @param num
     * @param qDate
     * @param hDate
     * @return
     */
    @Override
    public  Map<String,Object> viewCostRecord(long userId, Integer state, Integer page, Integer num, Date qDate, Date hDate) {
        Map<String,Object> map = new HashMap<>();
        if (state == 2){
            final List<UserCostRecord> userCostRecords = userMapper.viewCostRecord(userId, (page - 1) * num, num);
            final Integer integer = userMapper.viewCostCount(userId);
            map.put("total",integer);
            final List<UserCostRecordVo> tool = tool(userCostRecords);
            map.put("message",tool);
        }else {
            final List<UserCostRecord> userCostRecords = userMapper.viewCostRecordByStateAndTime(userId, state, (page - 1) * num, num, qDate, hDate);
            final Integer integer = userMapper.viewCostCountByTime(userId, qDate, hDate,state);
            final List<UserCostRecordVo> tool = tool(userCostRecords);
            map.put("total",integer);
            map.put("message",tool);
        }
        PageHelper.startPage(page,num);
        return map;
    }


    /**
     * 封装工具
     * @param userCostRecords
     * @return
     */
    private List<UserCostRecordVo> tool(List<UserCostRecord> userCostRecords){
        List<UserCostRecordVo> userCostRecordVos = new ArrayList<>();
        for (UserCostRecord userCostRecord : userCostRecords) {
            UserCostRecordVo userCostRecordVo = new UserCostRecordVo();
            BeanUtils.copyProperties(userCostRecord,userCostRecordVo);
            if (userCostRecord.getState() == 0){
                userCostRecordVo.setState("支付");
            }else if(userCostRecord.getState() == 1){
                userCostRecordVo.setState("退款");
            }
            userCostRecordVos.add(userCostRecordVo);
        }
        return userCostRecordVos;
    }




    /**
     * TODO 用户清空自己的余额
     * @param userId 用户id
     * @return 返回是否清空成功
     */
    private boolean cleanUserMoney(long userId) {
        return false;
    }


}
